package com.bwda.dsrs.systemservice.config;


import com.bwda.dsrs.base.centerbase.BaseConstants;
import com.bwda.dsrs.base.centerbase.BaseContextHandler;
import com.bwda.dsrs.common.enums.BusinessStatus;


import com.bwda.dsrs.systemservice.annotations.IgnoreClientToken;
import com.bwda.dsrs.systemservice.annotations.NeedRole;
import com.bwda.dsrs.systemservice.domain.Constants;
import com.bwda.dsrs.systemservice.domain.condition.cache.CacheCondition;
import com.bwda.dsrs.systemservice.domain.form.user.UserForm;
import com.bwda.dsrs.systemservice.domain.po.cache.CachePo;
import com.bwda.dsrs.systemservice.domain.po.role.RolePo;
import com.bwda.dsrs.systemservice.domain.po.user.UserPo;
import com.bwda.dsrs.systemservice.service.CacheService;
import com.bwda.dsrs.systemservice.service.RoleService;
import com.bwda.dsrs.systemservice.service.UserService;
import com.bwda.dsrs.systemservice.util.util.JwtTokenUtil;
import com.bwda.dsrs.systemservice.utils.IpAdrressUtil;
import com.bwda.dsrs.systemservice.utils.JsonUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
//import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.List;

/**
 * @description:
 * @author: yangjun
 * @create: 2019-06-05 14:51
 */
public class ServiceAuthRestInterceptor extends HandlerInterceptorAdapter {
    private Logger logger = LoggerFactory.getLogger(ServiceAuthRestInterceptor.class);

//    @Autowired
//    private RedisTemplate redisTemplate;
    @Autowired
    private RoleService roleService;
    @Autowired
    private CacheService cacheService;
    @Value("${feign.token}")
    private String feignToken;
    @Autowired
    private UserService userService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        if (!(handler instanceof HandlerMethod)) {
            return true;
        }

        //无需校验的请求，主要为版本信息，登录等
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        IgnoreClientToken annotation = handlerMethod.getBeanType().getAnnotation(IgnoreClientToken.class);
        if (annotation == null) {
            annotation = handlerMethod.getMethodAnnotation(IgnoreClientToken.class);
        }
        if (annotation != null) {
            return super.preHandle(request, response, handler);
        }


        //有feign token  先校验token
        String feignHeader = request.getHeader(BaseConstants.FEIGN_TOKEN);
        if (StringUtils.isNotEmpty(feignHeader)) {
            //是feign调用
            if (feignHeader.equals(feignToken)) {
                return true;
            } else {
                errorResponse(response, 201, "非法的调用");
                return false;
            }
        }

        //正常的请求校验
        String token = request.getHeader(BaseConstants.AUTHORIZATION);
        if (StringUtils.isEmpty(token)) {
            errorResponse(response, 202, "请重新登陆");
            return false;
        }
//        Object token1 = redisTemplate.opsForValue().get(token);
        CacheCondition cacheCondition = new CacheCondition();
        cacheCondition.setCacheKey(token);
        cacheCondition.setPageSize(Integer.MAX_VALUE);
        List<CachePo> cachePos = cacheService.queryList(cacheCondition);
        Object token1 = null;
        if (!CollectionUtils.isEmpty(cachePos)) {
            token1 = cachePos.get(0).getToken();
        }
        String token2 = token1 == null ? "" : (String) token1;
        if (StringUtils.isEmpty(token2)) {
            errorResponse(response, 202, "请重新登陆");
            return false;
        }
        String userCode = JwtTokenUtil.getUserCode(token);
        //有角色权限校验的请求
        NeedRole roleAnnotaion = handlerMethod.getBeanType().getAnnotation(NeedRole.class);
        if (roleAnnotaion == null) {
            roleAnnotaion = handlerMethod.getMethodAnnotation(NeedRole.class);
        }
        if (roleAnnotaion != null) {
            if (!checkRole(userCode, roleAnnotaion.value())) {
                errorResponse(response, 201, "您没有权限调用");
                return false;
            }
        }

        BaseContextHandler.setUserCode(userCode);
        BaseContextHandler.setUserName(JwtTokenUtil.getUserName(token));
        BaseContextHandler.setOrgId(JwtTokenUtil.getOrgId(token));
        BaseContextHandler.setOrgName(JwtTokenUtil.getOrgName(token));
        BaseContextHandler.setOrgAdminCode(JwtTokenUtil.getOrgAdminCode(token));
        BaseContextHandler.setAuthorization(token);
        BaseContextHandler.setIpAddr(IpAdrressUtil.getIpAdrress(request));

        return super.preHandle(request, response, handler);

    }

    /**
     * 检查用户角色
     *
     * @param userCode
     * @param value
     * @return
     */
    private boolean checkRole(String userCode, String[] value) {
        if (StringUtils.isEmpty(userCode)) {
            return false;
        }

        List<RolePo> rolePoList = roleService.queryUserRoleList(userCode);
        boolean result = false;
        for (RolePo po : rolePoList) {
            for (String roleCode : value) {
                if (roleCode.equals(po.getRoleCode())) {
                    result = true;
                    break;
                }
            }
            if (result) {
                break;
            }
        }
        return result;

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        BaseContextHandler.remove();
        super.afterCompletion(request, response, handler, ex);
    }

    private void errorResponse(final ServletResponse res, int errCode, String errMsg) {
        logger.debug("errorResponse");
        try {
            PrintWriter out = res.getWriter();
            res.setCharacterEncoding("UTF-8");
            res.setContentType("application/json; charset=utf-8");
            String retJson = JsonUtil.createJsonString(false, errCode, errMsg, Collections.EMPTY_MAP);

            out.print(retJson);
            out.flush();
        } catch (IOException e) {
            logger.info("security response error object error");
        }
    }
}
